package com.dm.cloud.utils.minio;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.services.s3.model.lifecycle.LifecycleFilter;
import com.amazonaws.services.s3.model.lifecycle.LifecyclePrefixPredicate;
import com.amazonaws.services.s3.model.lifecycle.LifecycleTagPredicate;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.google.common.collect.Multimap;
import io.minio.*;
import io.minio.credentials.Credentials;
import io.minio.errors.*;
import io.minio.messages.LifecycleConfiguration;
import io.minio.messages.Part;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CustomMinioClient extends MinioAsyncClient {

    /**
     * 需要清理的文件时间范围
     * 一天
     */
    private static int sevenDays = 1000 * 60 * 24;

    protected CustomMinioClient(MinioAsyncClient client) {
        super(client);
    }

    //初始化分块上传任务
    public String initMultiPartUpload(String bucket, String region, String object, Multimap<String, String> headers, Multimap<String, String> extraQueryParams) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException, ExecutionException, InterruptedException {
        CompletableFuture<CreateMultipartUploadResponse> response = this.createMultipartUploadAsync(bucket, region, object, headers, extraQueryParams);
        return response.get().result().uploadId();
    }

    //中止分块上传任务
    public String removeMultipartUpload(String bucket, String region, String object,String uploadId, Multimap<String, String> headers, Multimap<String, String> extraQueryParams) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException, ExecutionException, InterruptedException {
        CompletableFuture<AbortMultipartUploadResponse> response = this.abortMultipartUploadAsync(bucket, region, object, uploadId,headers, extraQueryParams);
        return response.get().uploadId();
    }

    //TODO 批量清理过期上传任务
    //获取不到桶内的上传任务 ListMultipartUploadsResponse result为空
    public void clearMultipartUpload(String bucket, String region, Multimap<String, String> headers, Multimap<String, String> extraQueryParams) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException, ExecutionException, InterruptedException {
        //通过MINIO接口获取桶未完成的上传任务
        CompletableFuture<ListMultipartUploadsResponse> multiUploads = this.listMultipartUploadsAsync(bucket, region,null,null,null,1000,null,null,headers, extraQueryParams);

        //        System.out.println(multiUploads);

//        直接调用 AWS接口 清理过期上传任务
        Date oneWeekAgo = new Date(System.currentTimeMillis() - sevenDays);
        Credentials creds = this.provider == null ? null : this.provider.fetch();

        AWSCredentials awsCredentials = new AWSCredentials() {
            @Override
            public String getAWSAccessKeyId() {
                return creds.accessKey();
            }

            @Override
            public String getAWSSecretKey() {
                return creds.secretKey();
            }
        };

        AmazonS3Client s3 = new AmazonS3Client(awsCredentials);
        s3.setEndpoint("http://127.0.0.1:9000");


        ListMultipartUploadsRequest allMultpartUploadsRequest =
                new ListMultipartUploadsRequest(bucket);
        MultipartUploadListing multipartUploadListing =
                s3.listMultipartUploads(allMultpartUploadsRequest);

        System.out.println(multipartUploadListing);

//        TransferManager tm = new TransferManager(s3);
//        try {
//            tm.abortMultipartUploads(bucket, oneWeekAgo);
//        } catch (Exception ex) {
//            throw new RuntimeException(ex.getMessage());
//        }
    }

    public void addBucketLifeCycleConfiguration(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException, ExecutionException, InterruptedException {
        Credentials creds = this.provider == null ? null : this.provider.fetch();
        AWSCredentials awsCredentials = new AWSCredentials() {
            @Override
            public String getAWSAccessKeyId() {
                return creds.accessKey();
            }

            @Override
            public String getAWSSecretKey() {
                return creds.secretKey();
            }
        };
        Regions clientRegion = Regions.DEFAULT_REGION;

        BucketLifecycleConfiguration.Rule rule2 = new BucketLifecycleConfiguration.Rule()
                .withId("Archive and then delete rule 2")
                .withPrefix("")
                .withExpirationInDays(3650)
                .withStatus(BucketLifecycleConfiguration.ENABLED)
                .withAbortIncompleteMultipartUpload(new AbortIncompleteMultipartUpload().withDaysAfterInitiation(1));

        BucketLifecycleConfiguration configuration = new BucketLifecycleConfiguration()
                .withRules(Arrays.asList(rule2));

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withCredentials(new AWSCredentialsProvider() {
                        @Override
                        public AWSCredentials getCredentials() {
                            return awsCredentials;
                        }

                        @Override
                        public void refresh() {

                        }
                    })
                    .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("http://127.0.0.1:9000",clientRegion.getName()))
                    .build();

            s3Client.setBucketLifecycleConfiguration(bucketName, configuration);
//            configuration = s3Client.getBucketLifecycleConfiguration(bucketName);
        } catch (AmazonServiceException e) {
            e.printStackTrace();
        } catch (SdkClientException e) {
            e.printStackTrace();
        }
        System.out.println("");
    }

    public void removeBucketLifeCycleConfiguration(String bucket) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException {
        GetBucketLifecycleArgs args = new GetBucketLifecycleArgs.Builder().bucket(bucket).build();
        CompletableFuture<LifecycleConfiguration> lc = this.getBucketLifecycle(args);
        if(lc.isDone()){
            this.deleteBucketLifecycle(new DeleteBucketLifecycleArgs.Builder().bucket(bucket).region(this.region).build());
        }
    }

    //合并分块文件
    public ObjectWriteResponse mergeMultipartUpload(String bucketName, String region, String objectName, String uploadId, Part[] parts, Multimap<String, String> extraHeaders, Multimap<String, String> extraQueryParams) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException, ExecutionException, InterruptedException {
 
        return this.completeMultipartUploadAsync(bucketName, region, objectName, uploadId, parts, extraHeaders, extraQueryParams).get();
    }

    //列出全部分块文件
    public ListPartsResponse listMultipart(String bucketName, String region, String objectName, Integer maxParts, Integer partNumberMarker, String uploadId, Multimap<String, String> extraHeaders, Multimap<String, String> extraQueryParams) throws NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, ServerException, XmlParserException, ErrorResponseException, InternalException, InvalidResponseException, ExecutionException, InterruptedException {
        return this.listPartsAsync(bucketName, region, objectName, maxParts, partNumberMarker, uploadId, extraHeaders, extraQueryParams).get();
    }
}